package fr.imag.ufrima.ima.project.ui.listerners;

import java.awt.Cursor;
import java.awt.Point;
import java.awt.event.MouseEvent;

import javax.swing.event.MouseInputAdapter;

import fr.imag.ufrima.ima.project.core.operations.Cut;
import fr.imag.ufrima.ima.project.ui.main.ImageDocument;
import fr.imag.ufrima.ima.project.ui.main.ImageProject;

public class SelectorListener extends MouseInputAdapter {
	private ImageProject imageProject;
	private ImageDocument id;
	private int w, h;
	private Cursor cursor;
    private Point start, end, last;
    boolean active, dragging, isSelectionSet, moveSelection;
 
    public SelectorListener(ImageProject frame) {
        this.imageProject = frame;
        this.id = null;
        this.h = this.w = 0;
        this.active = false;
        this.dragging = false;
        this.isSelectionSet = false;
        this.moveSelection = false;
    }
    
    private boolean isInside(Point p) {
    	int x1, y1, x2, y2;
    	x1 = (int) min(start.getX(), end.getX());
		y1 = (int) min(start.getY(), end.getY());
		x2 = (int) max(start.getX(), end.getX());
		y2 = (int) max(start.getY(), end.getY());
    	return (p.getX() > x1 && p.getY() > y1 && p.getX() < x2 && p.getY() < y2);
    }
    
    public void setActive() {
    	if(id == null)
    		this.id = this.imageProject.getCurrentImageDocument();
    	this.active = !this.active;
    	if(active) {
    		this.cursor = new Cursor(Cursor.CROSSHAIR_CURSOR);
			id.setCursor(this.cursor);
    	}
    	else {
    		this.cursor = new Cursor(Cursor.DEFAULT_CURSOR);
			id.setCursor(this.cursor);
    	}
    }
    
	public void mouseEntered(MouseEvent e){
		this.id = this.imageProject.getCurrentImageDocument();
		this.w = this.id.getImage().getWidth();
		this.h = this.id.getImage().getHeight();
	}
	
	public void mouseClicked(MouseEvent e) {
		int x1, y1, x2, y2, w, h;
	    if(active && isSelectionSet && isInside(e.getPoint()) && e.getClickCount() == 2) {
	    	x1 = (int) max(0, min(start.getX(), end.getX()));
			y1 = (int) max(0, min(start.getY(), end.getY()));
			x2 = (int) max(start.getX(), end.getX());
			y2 = (int) max(start.getY(), end.getY());
			w = (int) (x2-x1);
			h = (int) (y2-y1);
			//this.id.getImage().decouper(x1, y1, w, h);
			
			Cut cut = new Cut(id.getImage());
			cut.setCuttingRectangle(x1, y1, w, h);
			imageProject.applyOperation(cut);
			
			id.setSelectionFrame(start, start);
			isSelectionSet = false;
	        id.setIsSelectionSet(false);
			this.id.repaint();
			this.setActive();
			this.moveSelection = false;
	    }
	  }
 
    public void mousePressed(MouseEvent e) {
    	int x, y;
    	if(active) {
	        if(isSelectionSet && isInside(e.getPoint()) && e.getClickCount() == 1) {
    			this.moveSelection = true;
    			last = e.getPoint(); 
	        }
//	        else {
//	            x = (int) max(0, min(e.getX(), this.w));
//	        	y = (int) max(0, min(e.getY(), this.h));
//	        	this.start = new Point(x, y);
//	            id.setSelectionFrame(start, start);
//	            isSelectionSet = false;
//		        id.setIsSelectionSet(false);
//	            dragging = true;
//	            this.moveSelection = false;
//	        }
    	}
    }
 
    private double min(double a, double b) {
		if(a < b)
			return a;
		return b;
	}

	private double max(double a, double b) {
		if(a > b)
			return a;
		return b;
	}

	public void mouseReleased(MouseEvent e) {
    	if(active) {
    		isSelectionSet = true;
    		id.setIsSelectionSet(true);
    		this.id.setSelectionFrame(this.start, this.end);
    		dragging = false;
    		this.moveSelection = false;
    	}
    }
 
    public void mouseDragged(MouseEvent e) {
    	int x, y;
    	if(active) {
    		if(this.moveSelection) {
	        	int dx, dy;
	        	dx = (int) (e.getX()-last.getX());
	        	dy = (int) (e.getY()-last.getY());
	        	this.start = new Point((int) max(0, min(this.start.getX() + dx, this.w)), (int) max(0, min(this.start.getY() + dy, this.h)));
	        	this.end = new Point((int) max(0, min(this.end.getX() + dx, this.w)), (int) max(0, min(this.end.getY() + dy, this.h)));
	        	id.setIsSelectionSet(false);
	        	this.id.setSelectionFrame(this.start, this.end);
	        	last = e.getPoint();
	        }
    		else if(!dragging) {
	    		x = (int) max(0, min(e.getX(), this.w));
	        	y = (int) max(0, min(e.getY(), this.h));
	        	this.start = new Point(x, y);
	            id.setSelectionFrame(start, start);
	            isSelectionSet = false;
		        id.setIsSelectionSet(false);
	            dragging = true;
	            this.moveSelection = false;
	    	}
	    	else {
	        	x = (int) max(0, min(e.getX(), this.w));
	        	y = (int) max(0, min(e.getY(), this.h));
	        	this.end = new Point(x, y);
	        	this.id.setSelectionFrame(this.start, this.end);
	        }
    	}
    }
}
